package ar.com.mindset.geometrics_wi;

import ar.com.mindset.geometrics_wi.colorScheme.ColorScheme;
import ar.com.mindset.geometrics_wi.colorScheme.ContinuousColorScheme;
import ar.com.mindset.geometrics_wi.colorScheme.DiscreteColorScheme;
import ar.com.mindset.geometrics_wi.colorScheme.SolidColorScheme;
import ar.com.mindset.geometrics_wi.exceptions.GeometricsRuntimeException;

import java.util.HashMap;
import java.util.Map;

/**
 * @author http://www.mindset-designs.com
 */
public class GeometricsBuilder {

    public static enum RegionClickEffect {
        FADEOUTFADEIN, BLUR
    }

    public static enum RegionHideEffect {
        FADEOUT, EXPLODE, REDUCE
    }

    public static enum RegionShowEffect {
        FADEIN, IMPLODE, GROWUP
    }

    private RegionClickEffect regionClickEffect;
    private RegionHideEffect regionHideEffect;
    private RegionShowEffect regionShowEffect;

    private int height = -1;
    private int width = -1;
    private float scale = -1;
    private int x = -1;
    private int y = -1;

    private ColorScheme colorScheme;

    private String xmlDrawDataURL;
    private Map<String, Object> dataValues;


    public GeometricsBuilder() {
        this.dataValues = new HashMap<String, Object>();
    }

    /*
      * SETTINGS OF SIZE AND POSITION
      */
    public void setHeight(int height) {
        this.height = height;
    }

    public void setWidth(int width) {
        this.width = width;
    }

    public void setScale(float scale) {
        this.scale = scale;
    }

    public void setX(int x) {
        this.x = x;
    }

    public void setY(int y) {
        this.y = y;
    }

    private void setXMLSizeAndPosition(StringBuffer xml) {
        if (height == -1 || width == -1 || scale == -1) {
            throw new GeometricsRuntimeException("Must set all the mandatory size and position's values");
        }

        xml.append("<sizeAndPosition>");
        xml.append("<height>");
        xml.append(String.valueOf(height));
        xml.append("</height>");
        xml.append("<width>");
        xml.append(String.valueOf(width));
        xml.append("</width>");
        xml.append("<scale>");
        xml.append(String.valueOf(scale));
        xml.append("</scale>");
        if (x != -1) {
            xml.append("<x>");
            xml.append(String.valueOf(x));
            xml.append("</x>");
        }
        if (y != -1) {
            xml.append("<y>");
            xml.append(String.valueOf(y));
            xml.append("</y>");
        }
        xml.append("</sizeAndPosition>");
    }

    /*
      * SETTINGS OF REGIONS EFFECTS
      */
    public void setRegionClickEffect(RegionClickEffect regionClickEffect) {
        this.regionClickEffect = regionClickEffect;
    }

    public void setRegionHideEffect(RegionHideEffect regionHideEffect) {
        this.regionHideEffect = regionHideEffect;
    }

    public void setRegionShowEffect(RegionShowEffect regionShowEffect) {
        this.regionShowEffect = regionShowEffect;
    }

    private void setXMLEffectsStrategies(StringBuffer xml) {
        if (this.regionClickEffect != null || this.regionHideEffect != null || this.regionShowEffect != null) {
            xml.append("<effectsStrategies>");
            if (this.regionClickEffect != null) {
                xml.append("<regionsClick>");
                xml.append(this.regionClickEffect.name());
                xml.append("</regionsClick>");
            }
            if (this.regionHideEffect != null) {
                xml.append("<regionsHide>");
                xml.append(this.regionHideEffect.name());
                xml.append("</regionsHide>");
            }
            if (this.regionShowEffect != null) {
                xml.append("<regionsShow>");
                xml.append(this.regionShowEffect.name());
                xml.append("</regionsShow>");
            }
            xml.append("</effectsStrategies>");
        }
    }

    /*
      * SETTINGS OF COLOR SCHEME
      */
    public SolidColorScheme useSolidColorScheme() {
        this.colorScheme = new SolidColorScheme();
        return (SolidColorScheme) this.colorScheme;
    }

    public DiscreteColorScheme useDiscreteColorScheme() {
        this.colorScheme = new DiscreteColorScheme();
        return (DiscreteColorScheme) this.colorScheme;
    }

    public ContinuousColorScheme useContinuousColorScheme() {
        this.colorScheme = new ContinuousColorScheme();
        return (ContinuousColorScheme) this.colorScheme;
    }


    /*
      * SETTINGS OF THE DATA
      */
    public void setXmlDrawDataURL(String xmlDrawDataURL) {
        this.xmlDrawDataURL = xmlDrawDataURL;
    }

    public void addValue(String key, Object value) {
        this.dataValues.put(key, value);
    }

    private void setXMLData(StringBuffer xml) {
        if (xmlDrawDataURL == null) {
            throw new GeometricsRuntimeException("Must set an URL in xmlDrawDataURL");
        }
        if (dataValues.size() == 0) {
            throw new GeometricsRuntimeException("Must set data values");
        }

        xml.append("<data xmlDrawDataURL='");
        xml.append(this.xmlDrawDataURL);
        xml.append("'>");
        xml.append("<values>");
        for (String key : this.dataValues.keySet()) {
            xml.append(key);
            xml.append("=");
            xml.append(this.dataValues.get(key));
            xml.append(";");
        }
        xml.append("</values></data>");
    }


    private String getXMLConfig() {
        StringBuffer xml = new StringBuffer(1000);

        xml.append("<?xml version='1.0' encoding='UTF-8'?>");
        xml.append("<geometrics-wi xsi:schemaLocation='http://www.mindset.com.ar geometrics-wi.xsd'");
        xml.append(" xmlns='http://www.mindset.com.ar' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'>");

        xml.append("<config>");

        this.setXMLEffectsStrategies(xml);
        this.setXMLSizeAndPosition(xml);
        if (colorScheme != null) {
            this.colorScheme.write(xml);
        }
        xml.append("</config>");

        this.setXMLData(xml);

        xml.append("</geometrics-wi>");

        return xml.toString();
    }

    /**
     * It builds the html code for embeding the geometrics report SWF with the set configuration.
     *
     * @return a String of the html code.
     */
    public String getReportCode() {
        try {
            return

                    "<script language=\"JavaScript\" type=\"text/javascript\"> " +
                            "var hasProductInstall = DetectFlashVer(6, 0, 65); " +

                            "var hasRequestedVersion = DetectFlashVer(requiredMajorVersion, requiredMinorVersion, requiredRevision); " +

                            "if ( hasProductInstall && !hasRequestedVersion ) { " +
                            "	var MMPlayerType = (isIE == true) ? \"ActiveX\" : \"PlugIn\"; " +
                            "	var MMredirectURL = window.location; " +
                            "    document.title = document.title.slice(0, 47) + \" - Flash Player Installation\"; " +
                            "    var MMdoctitle = document.title; " +

                            "	AC_FL_RunContent( " +
                            "		\"src\", \"playerProductInstall\", " +
                            "		\"FlashVars\", \"MMredirectURL=\"+MMredirectURL+'&MMplayerType='+MMPlayerType+'&MMdoctitle='+MMdoctitle+\"\", " +
                            "		\"width\", \"" + this.width + "\", " +
                            "		\"height\", \"" + this.height + "\", " +
                            "		\"align\", \"middle\", " +
                            "		\"id\", \"GeometricsWI\", " +
                            "		\"quality\", \"high\", " +
                            "		\"bgcolor\", \"#869ca7\", " +
                            "		\"name\", \"GeometricsWI\", " +
                            "		\"flashvars\",\"isXML=true&xmlConfig=" + this.getXMLConfig() + "\"," +
                            "		\"allowScriptAccess\",\"sameDomain\", " +
                            "		\"type\", \"application/x-shockwave-flash\", " +
                            "		\"pluginspage\", \"http://www.adobe.com/go/getflashplayer\" " +
                            "	); " +
                            "} else if (hasRequestedVersion) { " +
                            "	AC_FL_RunContent( " +
                            "			\"src\", \"GeometricsWI\", " +
                            "			\"width\", \"" + this.width + "\", " +
                            "			\"height\", \"" + this.height + "\", " +
                            "			\"align\", \"middle\", " +
                            "			\"id\", \"GeometricsWI\", " +
                            "			\"quality\", \"high\", " +
                            "			\"bgcolor\", \"#869ca7\", " +
                            "			\"name\", \"GeometricsWI\", " +
                            "			\"flashvars\",\"isXML=true&xmlConfig=" + this.getXMLConfig() + "\"," +
                            "			\"allowScriptAccess\",\"sameDomain\", " +
                            "			\"type\", \"application/x-shockwave-flash\", " +
                            "			\"pluginspage\", \"http://www.adobe.com/go/getflashplayer\" " +
                            "	); " +
                            "  } else {  " +
                            "   var alternateContent = 'Alternate HTML content should be placed here. ' " +
                            "  	+ 'This content requires the Adobe Flash Player. ' " +
                            "   	+ '<a href=http://www.adobe.com/go/getflash/>Get Flash</a>'; " +
                            "    document.write(alternateContent);  " +
                            "  } " +
                            "</script> " +
                            "<noscript> " +
                            "  	<object classid=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\" " +
                            "			id=\"GeometricsWI\" width=\"" + this.width + "\" height=\"" + this.height + "\" " +
                            "			codebase=\"http://fpdownload.macromedia.com/get/flashplayer/current/swflash.cab\"> " +
                            "			<param name=\"movie\" value=\"GeometricsWI.swf\" /> " +
                            "			<param name=\"quality\" value=\"high\" /> " +
                            "			<param name=\"bgcolor\" value=\"#869ca7\" /> " +
                            "			<param name=\"allowScriptAccess\" value=\"sameDomain\" /> " +
                            "			<embed src=\"GeometricsWI.swf\" quality=\"high\" bgcolor=\"#869ca7\" " +
                            "				width=\"" + this.width + "\" height=\"" + this.height + "\" name=\"GeometricsWI\" align=\"middle\" " +
                            "				play=\"true\" " +
                            "				loop=\"false\" " +
                            "				quality=\"high\" " +
                            "				allowScriptAccess=\"sameDomain\" " +
                            "				type=\"application/x-shockwave-flash\" " +
                            "				pluginspage=\"http://www.adobe.com/go/getflashplayer\"> " +
                            "			</embed> " +
                            "	</object> " +
                            "</noscript> ";

        } catch (GeometricsRuntimeException geoEx) {
            throw geoEx;
        } catch (Exception ex) {
            throw new GeometricsRuntimeException("A problem has occurred during the construction of the report: " + ex.getMessage(), ex);
        }
    }

    /**
     * It builds the html code for the header which include all the javascript functions needed.
     * You must include this code in the header tag of your page.
     *
     * @return a String with the html code.
     */
    public String getHeaderCode() {
        return
                "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />" +
                        "" +
                        "		<script language=\"javascript\" type=\"text/javascript\">" +
                        "			var isIE  = (navigator.appVersion.indexOf(\"MSIE\") != -1) ? true : false;" +
                        "			var isWin = (navigator.appVersion.toLowerCase().indexOf(\"win\") != -1) ? true : false;" +
                        "			var isOpera = (navigator.userAgent.indexOf(\"Opera\") != -1) ? true : false;" +
                        "			" +
                        "			function ControlVersion()" +
                        "			{" +
                        "				var version;" +
                        "				var axo;" +
                        "				var e;" +
                        "			" +
                        "			" +
                        "				try {" +
                        "					axo = new ActiveXObject(\"ShockwaveFlash.ShockwaveFlash.7\");" +
                        "					version = axo.GetVariable(\"$version\");" +
                        "				} catch (e) {" +
                        "				}" +
                        "			" +
                        "				if (!version)" +
                        "				{" +
                        "					try {" +
                        "						axo = new ActiveXObject(\"ShockwaveFlash.ShockwaveFlash.6\");" +
                        "						" +
                        "						" +
                        "						version = \"WIN 6,0,21,0\";" +
                        "			" +
                        "						axo.AllowScriptAccess = \"always\";" +
                        "			" +
                        "						version = axo.GetVariable(\"$version\");" +
                        "			" +
                        "					} catch (e) {" +
                        "					}" +
                        "				}" +
                        "			" +
                        "				if (!version)" +
                        "				{" +
                        "					try {" +
                        "						axo = new ActiveXObject(\"ShockwaveFlash.ShockwaveFlash.3\");" +
                        "						version = axo.GetVariable(\"$version\");" +
                        "					} catch (e) {" +
                        "					}" +
                        "				}" +
                        "			" +
                        "				if (!version)" +
                        "				{" +
                        "					try {" +
                        "						axo = new ActiveXObject(\"ShockwaveFlash.ShockwaveFlash.3\");" +
                        "						version = \"WIN 3,0,18,0\";" +
                        "					} catch (e) {" +
                        "					}" +
                        "				}" +
                        "			" +
                        "				if (!version)" +
                        "				{" +
                        "					try {" +
                        "						axo = new ActiveXObject(\"ShockwaveFlash.ShockwaveFlash\");" +
                        "						version = \"WIN 2,0,0,11\";" +
                        "					} catch (e) {" +
                        "						version = -1;" +
                        "					}" +
                        "				}" +
                        "				" +
                        "				return version;" +
                        "			}" +
                        "			" +
                        "			function GetSwfVer(){" +
                        "				var flashVer = -1;" +
                        "				" +
                        "				if (navigator.plugins != null && navigator.plugins.length > 0) {" +
                        "					if (navigator.plugins[\"Shockwave Flash 2.0\"] || navigator.plugins[\"Shockwave Flash\"]) {" +
                        "						var swVer2 = navigator.plugins[\"Shockwave Flash 2.0\"] ? \" 2.0\" : \"\";" +
                        "						var flashDescription = navigator.plugins[\"Shockwave Flash\" + swVer2].description;" +
                        "						var descArray = flashDescription.split(\" \");" +
                        "						var tempArrayMajor = descArray[2].split(\".\");			" +
                        "						var versionMajor = tempArrayMajor[0];" +
                        "						var versionMinor = tempArrayMajor[1];" +
                        "						var versionRevision = descArray[3];" +
                        "						if (versionRevision == \"\") {" +
                        "							versionRevision = descArray[4];" +
                        "						}" +
                        "						if (versionRevision[0] == \"d\") {" +
                        "							versionRevision = versionRevision.substring(1);" +
                        "						} else if (versionRevision[0] == \"r\") {" +
                        "							versionRevision = versionRevision.substring(1);" +
                        "							if (versionRevision.indexOf(\"d\") > 0) {" +
                        "								versionRevision = versionRevision.substring(0, versionRevision.indexOf(\"d\"));" +
                        "							}" +
                        "						} else if (versionRevision[0] == \"b\") {" +
                        "							versionRevision = versionRevision.substring(1);" +
                        "						}" +
                        "						var flashVer = versionMajor + \".\" + versionMinor + \".\" + versionRevision;" +
                        "					}" +
                        "				}" +
                        "				else if (navigator.userAgent.toLowerCase().indexOf(\"webtv/2.6\") != -1) flashVer = 4;" +
                        "				else if (navigator.userAgent.toLowerCase().indexOf(\"webtv/2.5\") != -1) flashVer = 3;" +
                        "				else if (navigator.userAgent.toLowerCase().indexOf(\"webtv\") != -1) flashVer = 2;" +
                        "				else if ( isIE && isWin && !isOpera ) {" +
                        "					flashVer = ControlVersion();" +
                        "				}" +
                        "				return flashVer;" +
                        "			}" +
                        "			" +
                        "			function DetectFlashVer(reqMajorVer, reqMinorVer, reqRevision)" +
                        "			{" +
                        "				versionStr = GetSwfVer();" +
                        "				if (versionStr == -1 ) {" +
                        "					return false;" +
                        "				} else if (versionStr != 0) {" +
                        "					if(isIE && isWin && !isOpera) {" +
                        "						tempArray         = versionStr.split(\" \"); 	" +
                        "						tempString        = tempArray[1];			" +
                        "						versionArray      = tempString.split(\",\");	" +
                        "					} else {" +
                        "						versionArray      = versionStr.split(\".\");" +
                        "					}" +
                        "					var versionMajor      = versionArray[0];" +
                        "					var versionMinor      = versionArray[1];" +
                        "					var versionRevision   = versionArray[2];" +
                        "			" +
                        "					if (versionMajor > parseFloat(reqMajorVer)) {" +
                        "						return true;" +
                        "					} else if (versionMajor == parseFloat(reqMajorVer)) {" +
                        "						if (versionMinor > parseFloat(reqMinorVer))" +
                        "							return true;" +
                        "						else if (versionMinor == parseFloat(reqMinorVer)) {" +
                        "							if (versionRevision >= parseFloat(reqRevision))" +
                        "								return true;" +
                        "						}" +
                        "					}" +
                        "					return false;" +
                        "				}" +
                        "			}" +
                        "			" +
                        "			function AC_AddExtension(src, ext)" +
                        "			{" +
                        "			  if (src.indexOf('?') != -1)" +
                        "			    return src.replace(/\\?/, ext+'?'); " +
                        "			  else" +
                        "			    return src + ext;" +
                        "			}" +
                        "			" +
                        "			function AC_Generateobj(objAttrs, params, embedAttrs) " +
                        "			{ " +
                        "			    var str = '';" +
                        "			    if (isIE && isWin && !isOpera)" +
                        "			    {" +
                        "			  		str += '<object ';" +
                        "			  		for (var i in objAttrs)" +
                        "			  			str += i + '=\"' + objAttrs[i] + '\" ';" +
                        "			  		str += '>';" +
                        "			  		for (var i in params)" +
                        "			  			str += '<param name=\"' + i + '\" value=\"' + params[i] + '\" /> ';" +
                        "			  		str += '</object>';" +
                        "			    } else {" +
                        "			  		str += '<embed ';" +
                        "			  		for (var i in embedAttrs)" +
                        "			  			str += i + '=\"' + embedAttrs[i] + '\" ';" +
                        "			  		str += '> </embed>';" +
                        "			    }" +
                        "			" +
                        "			    document.write(str);" +
                        "			}" +
                        "			" +
                        "			function AC_FL_RunContent(){" +
                        "			  var ret = " +
                        "			    AC_GetArgs" +
                        "			    (  arguments, \".swf\", \"movie\", \"clsid:d27cdb6e-ae6d-11cf-96b8-444553540000\"" +
                        "			     , \"application/x-shockwave-flash\"" +
                        "			    );" +
                        "			  AC_Generateobj(ret.objAttrs, ret.params, ret.embedAttrs);" +
                        "			}" +
                        "			" +
                        "			function AC_GetArgs(args, ext, srcParamName, classid, mimeType){" +
                        "			  var ret = new Object();" +
                        "			  ret.embedAttrs = new Object();" +
                        "			  ret.params = new Object();" +
                        "			  ret.objAttrs = new Object();" +
                        "			  for (var i=0; i < args.length; i=i+2){" +
                        "			    var currArg = args[i].toLowerCase();    " +
                        "			" +
                        "			    switch (currArg){	" +
                        "			      case \"classid\":" +
                        "			        break;" +
                        "			      case \"pluginspage\":" +
                        "			        ret.embedAttrs[args[i]] = args[i+1];" +
                        "			        break;" +
                        "			      case \"src\":" +
                        "			      case \"movie\":	" +
                        "			        args[i+1] = AC_AddExtension(args[i+1], ext);" +
                        "			        ret.embedAttrs[\"src\"] = args[i+1];" +
                        "			        ret.params[srcParamName] = args[i+1];" +
                        "			        break;" +
                        "			      case \"onafterupdate\":" +
                        "			      case \"onbeforeupdate\":" +
                        "			      case \"onblur\":" +
                        "			      case \"oncellchange\":" +
                        "			      case \"onclick\":" +
                        "			      case \"ondblClick\":" +
                        "			      case \"ondrag\":" +
                        "			      case \"ondragend\":" +
                        "			      case \"ondragenter\":" +
                        "			      case \"ondragleave\":" +
                        "			      case \"ondragover\":" +
                        "			      case \"ondrop\":" +
                        "			      case \"onfinish\":" +
                        "			      case \"onfocus\":" +
                        "			      case \"onhelp\":" +
                        "			      case \"onmousedown\":" +
                        "			      case \"onmouseup\":" +
                        "			      case \"onmouseover\":" +
                        "			      case \"onmousemove\":" +
                        "			      case \"onmouseout\":" +
                        "			      case \"onkeypress\":" +
                        "			      case \"onkeydown\":" +
                        "			      case \"onkeyup\":" +
                        "			      case \"onload\":" +
                        "			      case \"onlosecapture\":" +
                        "			      case \"onpropertychange\":" +
                        "			      case \"onreadystatechange\":" +
                        "			      case \"onrowsdelete\":" +
                        "			      case \"onrowenter\":" +
                        "			      case \"onrowexit\":" +
                        "			      case \"onrowsinserted\":" +
                        "			      case \"onstart\":" +
                        "			      case \"onscroll\":" +
                        "			      case \"onbeforeeditfocus\":" +
                        "			      case \"onactivate\":" +
                        "			      case \"onbeforedeactivate\":" +
                        "			      case \"ondeactivate\":" +
                        "			      case \"type\":" +
                        "			      case \"codebase\":" +
                        "			        ret.objAttrs[args[i]] = args[i+1];" +
                        "			        break;" +
                        "			      case \"id\":" +
                        "			      case \"width\":" +
                        "			      case \"height\":" +
                        "			      case \"align\":" +
                        "			      case \"vspace\": " +
                        "			      case \"hspace\":" +
                        "			      case \"class\":" +
                        "			      case \"title\":" +
                        "			      case \"accesskey\":" +
                        "			      case \"name\":" +
                        "			      case \"tabindex\":" +
                        "			        ret.embedAttrs[args[i]] = ret.objAttrs[args[i]] = args[i+1];" +
                        "			        break;" +
                        "			      default:" +
                        "			        ret.embedAttrs[args[i]] = ret.params[args[i]] = args[i+1];" +
                        "			    }" +
                        "			  }" +
                        "			  ret.objAttrs[\"classid\"] = classid;" +
                        "			  if (mimeType) ret.embedAttrs[\"type\"] = mimeType;" +
                        "			  return ret;" +
                        "			}" +
                        "		</script>" +
                        "" +
                        "		<style>" +
                        "		body { margin: 0px; overflow:hidden }" +
                        "		</style>" +
                        "" +
                        "		<script language=\"JavaScript\" type=\"text/javascript\">" +
                        "		var requiredMajorVersion = 9;" +
                        "		var requiredMinorVersion = 0;" +
                        "		var requiredRevision = 124;" +
                        "		</script>";
    }
}
